<?php

namespace App\Models\Traits;

use Carbon\Carbon;
use App\Models\GoldRecord;
use Brick\Math\RoundingMode;

trait GoldProductTrait
{
	public function isLocking(): bool
	{
		return $this->goldRound->is_locking;
	}

	public function isDisabled(): bool
	{
		return (bool)$this->disabled_at;
	}

    public function lastValidRecord()
    {
        return GoldRecord::whereDate('created_at', '<=', Carbon::today())
            ->where('gold_product_id', $this->id)
            ->whereNotNull('paid_at')
            ->orderByDesc('id')
            ->first();
    }

    public function allRound(): int
    {
        $allRounds = (int)$this->goldSeed->all_rounds;
        return max($allRounds, 0);
    }

    public function currentRound(): int
    {
        /**
         * @var GoldRecord $last
         */
        $last = $this->lastValidRecord();
        return $last ? (int)$last->round : 0;
    }

    public function isTakenToday(): bool
    {
        /**
         * @var GoldRecord $last
         */
        $last = $this->lastValidRecord();
        return $last and $last->created_at->isCurrentDay();
    }

    public function willBeLastRound(): bool
    {
        // next record will be last.
        $allRound = (int)$this->goldSeed->all_rounds;
        $currentRound = $this->currentRound();
        return $allRound > 0 and $currentRound+1 == $allRound;
    }

    public function isLastRound(): bool
    {
        // already last round after record had been paid.
        $currentRound = $this->currentRound();

        if ($currentRound > 0) {
            $allRound = $this->allRound();
            return $allRound > 0 and $currentRound >= $allRound;
        } else {
            return false;
        }
    }

    public function isSplit(): bool
    {
        return $this->goldSplits()->exists();
    }

    public function isSplitSettled(): bool
    {
        return $this->splitsAllCount() == $this->splitsSettledCount();
    }

    public function splitsAllCount(): int
    {
        return max((int)$this->goldSeed->split_amount, 0);
    }

    public function splitsAllMoney()
    {
        $initPrice = big_decimal($this->goldSeed->init_price);
        if ($initPrice->isLessThanOrEqualTo(0)) {
            return big_decimal(0);
        } else {
            return $initPrice->multipliedBy($this->splitsAllCount());
        }
    }

    public function splitsSettledCount(): int
    {
        return $this->goldSplits()->whereNotNull('settled_at')->count();
    }

    public function splitsSettledMoney()
    {
        return $this->goldSplits()->whereNotNull('settled_at')->sum('split_price');
    }

	public function isLastValidRecordMocked(): bool
	{
        /**
         * @var GoldRecord $last
         */
		$last = $this->lastValidRecord();
		return $last ? $last->user->is_mock : false;
	}

	public function allPriceLast()
	{
        /**
         * @var GoldRecord $record
         */
		$record = $this->lastValidRecord();
		return $record ? big_decimal($record->record_all_price) : big_decimal(0);
	}

	public function allPriceToday()
	{
		$priceLast = $this->allPriceLast();
		if ($priceLast->isLessThanOrEqualTo(0)) {
			return big_decimal($this->goldSeed->init_price);
		}

		if ($this->isLastValidRecordMocked()) {
			return $priceLast;
		}

        /**
         * @var GoldRecord $lastRecord
         */
		if ($lastRecord = $this->lastValidRecord()) {
			return big_decimal($lastRecord->resell_all_price);
		}

        $premiumPercent = cs('storm')->round_premium_percent;
		if ($premiumPercent->isLessThanOrEqualTo(0)) {
			return big_decimal($this->goldSeed->init_price);
		}
		$price = $priceLast->plus($priceLast->multipliedBy($premiumPercent->multipliedBy(0.01)));
		return $price->toScale(2, RoundingMode::HALF_UP);
	}

    public function netPriceToday()
    {
        if ($this->currentRound() <= 0) {
            $allPriceToday = $this->allPriceToday();
            $net = $allPriceToday->multipliedBy(3)
                ->dividedBy(16, RoundingMode::HALF_UP);
        } else {
            $lastRecord = $this->lastValidRecord();
            $net = big_decimal($lastRecord->pay_net_price)
                ->plus($lastRecord->pay_gold_beans)
                ->plus($lastRecord->profit_after_resold);
        }
        return $net->toScale(2, RoundingMode::HALF_UP);
    }

    public function cashPriceToday()
    {
        $allPrice = $this->allPriceToday();
        $netPrice = $this->netPriceToday();
        return $allPrice->minus($netPrice);
    }

    public function goldBeansToday()
    {
        $resellBeansPercent = big_decimal(cs('storm')->resell_need_beans_percent);
        return $this->allPriceToday()
            ->multipliedBy($resellBeansPercent->multipliedBy(0.01))
            ->toScale(2, RoundingMode::HALF_UP);
    }

    public function willGetProfitAfterResold()
    {
        $net = $this->netPriceToday();

        $percent = $this->willBeLastRound()
            ? big_decimal(cs('storm')->last_round_profit_percent)
            : big_decimal(cs('storm')->move_round_profit_percent);

        $profit = $net->multipliedBy($percent->multipliedBy(0.01));

        return $profit->toScale(2, RoundingMode::HALF_UP);
    }

	public function allPriceNext()
	{
		$priceToday = $this->allPriceToday();
        $premiumPercent = big_decimal(cs('storm')->round_premium_percent);
        if ($premiumPercent->isLessThanOrEqualTo(0)) {
            $priceTomorrow = $priceToday;
        } else {
            $priceTomorrow = $priceToday->plus($priceToday->multipliedBy($premiumPercent->multipliedBy(0.01)));
        }
		return $priceTomorrow->toScale(2, RoundingMode::HALF_UP);
	}
}
